#pragma once
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstdlib>
#include <cstring>
#include <set>
#include "common.hpp"
#include <iostream>
#include <vector>
#include <string>
class Addr
{   
    Addr()
    {
        pthread_mutex_init(&_mtx, nullptr);
    }
    Addr(const Addr&) = delete;
    Addr& operator=(const Addr&) = delete;
public:
    class GG
    {
    public:
        ~GG()
        {
            if(p != nullptr){
                delete p;
                p = nullptr;
            }
        }
    };
    static Addr* GetInstance()
    {
        if(p == nullptr)
        {
            LockGuard lock(&mutex);
            if(p == nullptr)
            {
                p = new Addr;
            }
        }
        return p;
    }


    void Add(const struct sockaddr_in& client)
    {
        // std::cout << "add... " << std::endl;
        uint16_t port = ntohs(client.sin_port);
        //const char* inet_ntop(int af, const void* src, char* dst, socklen_t size);
        char buffer[20];
        const char* ret = inet_ntop(AF_INET, &client.sin_addr.s_addr, buffer, sizeof(buffer));
        std::cout << ret << " " << port << std::endl;
        {
            LockGuard lock(&_mtx);
            _st.insert(std::make_pair(ret, port));
        }
    }

    void Send(const std::string& message, int sockfd)
    {
        // std::cout << "send... "<< std::endl;
        LockGuard lock(&_mtx);
        std::vector<std::pair<std::string, uint16_t>> del;
        for(const auto& [ip, port]:_st)
        {
            struct sockaddr_in client;
            memset(&client, 0, sizeof(client));
            client.sin_family = AF_INET;
            client.sin_port = htons(port);
            client.sin_addr.s_addr = inet_addr(ip.c_str());
            int n = sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&client, sizeof(client));
            if(n <= 0)
            {
                del.emplace_back(ip, port);
                std::cout << "client : " << ip << " " << port << "退出"<< std::endl;
            }
            // std::cout << "client??? : " << message << std::endl;
        }
        for(const auto& e :del)
            _st.erase(e);
    }

    void Delete(const struct sockaddr_in& client)
    {
        uint16_t port = ntohs(client.sin_port);
        //const char* inet_ntop(int af, const void* src, char* dst, socklen_t size);
        char buffer[20];
        const char* ret = inet_ntop(AF_INET, &client.sin_addr.s_addr, buffer, sizeof(buffer));
        {
            LockGuard lock(&_mtx);
            _st.erase(std::make_pair(ret, port));
        }
    }

    std::string ip_port(const struct sockaddr_in& client)
    {
        uint16_t port = ntohs(client.sin_port);
        //const char* inet_ntop(int af, const void* src, char* dst, socklen_t size);
        char buffer[20];
        const char* ret = inet_ntop(AF_INET, &client.sin_addr.s_addr, buffer, sizeof(buffer));
        std::string r = buffer;
        r += (":" + std::to_string(port));
        return r;
    }
    ~Addr()
    {
        pthread_mutex_destroy(&_mtx);
    }
private:
    pthread_mutex_t _mtx;
    static pthread_mutex_t mutex; 
    std::set<std::pair<std::string, uint16_t>> _st;
    static Addr* p;
    static GG g;
};

Addr* Addr::p = nullptr;
pthread_mutex_t Addr::mutex = PTHREAD_MUTEX_INITIALIZER;
Addr::GG Addr::g;